#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <cmath>
#include <sstream>
#include <QInputDialog>
#include "QLogTool.h"
#include "StyleSheetStub.h"
#include "sstream"

struct digitubeFrm // 48 bytes
{
    uint32_t currChannel = 0;
    uint16_t currValue = 0;
    uint16_t currAdVal = 0;
    uint16_t accCurve[2][10];
};

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    StyleSheetStub::LoadStyleSheet(this);
    Init();
}

MainWindow::~MainWindow()
{
    m_devLinker->close();
    delete ui;
}

uint32_t MainWindow::Init()
{
    connect(&QLogTool::Instance(), &QLogTool::SigLogStaBar, this, &Log);

    m_dev = make_shared<DevAccuator>();
    if (m_dev == nullptr) { return ERR_ASSERT; }
    ERRCODE ret = m_dev->Initialize(DEVTYPENAME_CALIBER);
    if (ret != ERR_SUCCESS) {
        LOG("Device Initalize Failed with %u", ret);
        return ret;
    }
    m_dev->start();
    connect(this, &SigGetDevDump, m_dev.get(), &KzDevice::SlotRequestDump);

    m_devLinker = make_unique<DeviceLinker>(this);
    StyleSheetStub::LoadStyleSheet(m_devLinker.get());
    if (m_devLinker == nullptr) { return ERR_ASSERT; }
    m_devLinker->ConfigStaticHandler(m_dev->GetStatic());
    connect(m_devLinker.get(), &DeviceLinker::SigLinkCmd, m_dev.get(), &KzDevice::SlotPortLink);

    ui->lbSlvDataVolt->setStyleSheet("color:#209FDF;");
    ui->lbSlvDataCurr->setAlignment(Qt::AlignRight | Qt::AlignVCenter);
    ui->lbSlvDataCurr->setStyleSheet("color:#DF725D;");
    InitChart();
    InitChart(ui->lbPlot_VoltPara, ADC_CHANNEL_VOLT);
    InitChart(ui->lbPlot_CurrPara, ADC_CHANNEL_CURR);

    ui->txRealVal->installEventFilter(this);
    connect(this, &SigSetCurrData, m_dev.get(), &DevAccuator::SlotSetCurrData);
    connect(this, &SigSetFixedData, m_dev.get(), &DevAccuator::SlotSetCurrData);
    ui->txCalcRaw->setEnabled(false);
    ui->txCalcVal->setEnabled(false);

    Update();

    m_timr = make_unique<QTimer>(this);
    if (m_timr == nullptr) { return ERR_ASSERT; }
    connect(m_timr.get(), SIGNAL(timeout()), this, SLOT(Update()));
    m_timr->start(static_cast<int>(UI_PERIOD));

    LOG("init done");
    return ERR_SUCCESS;
}

uint32_t MainWindow::InitChart()
{
    m_chart = new QChart();
    m_chartView = new QChartView(ui->lbPlot);
    m_curve = new QLineSeries();
    QChart* pChart = m_chart;
    if (m_chartView == nullptr || pChart == nullptr || m_curve == nullptr) {
        return ERR_ASSERT;
    }

    m_curve->setName("VOLT");
    pChart->addSeries(m_curve);
    StyleSheetStub::CfgChartStyle(pChart);
    StyleSheetStub::CfgChartRange(pChart, 0, 10, 0, 4096);
    m_chartView->setBackgroundBrush(QColor(0x44,0x44,0x44));
    m_chartView->setChart(m_chart);
    m_chartView->setGeometry(0, 0, ui->lbPlot->width(), ui->lbPlot->height());

    return ERR_SUCCESS;
}

uint32_t MainWindow::InitChart(QLabel* lable, size_t curveIdx)
{
    m_ptsChart[curveIdx] = new QChart();
    m_ptsChartView[curveIdx] = new QChartView(lable);
    m_ptsCurve[curveIdx] = new QScatterSeries();
    QChart* pChart = m_ptsChart[curveIdx];
    QChartView* pView = m_ptsChartView[curveIdx];
    QScatterSeries* pCurve = m_ptsCurve[curveIdx];
    if (pChart == nullptr || pView == nullptr || m_ptsCurve[curveIdx] == nullptr) {
        return ERR_ASSERT;
    }
    pCurve->setMarkerSize(5);
    pChart->addSeries(m_ptsCurve[curveIdx]);
    StyleSheetStub::CfgChartStyle(pChart);
    StyleSheetStub::CfgChartRange(pChart, 0, 400000, 0, 5000);
    pView->setBackgroundBrush(QColor(0x44,0x44,0x44));
    pView->setChart(pChart);
    pView->setGeometry(0, 0, lable->width(), lable->height());

    return ERR_SUCCESS;
}

void MainWindow::Update()
{
    if (m_dev->GetState() == KzDevice::DEV_RDY) {
        StyleSheetStub::CfgBtStyle(ui->btOpenDev,   StyleSheetStub::BtReady, "关闭设备");
        StyleSheetStub::CfgBtStyle(ui->btReadPara,  StyleSheetStub::BtReady);
        StyleSheetStub::CfgBtStyle(ui->btWritePara, StyleSheetStub::BtReady);
    } else {
        StyleSheetStub::CfgBtStyle(ui->btOpenDev,   StyleSheetStub::BtReady,   "打开设备");
        StyleSheetStub::CfgBtStyle(ui->btReadPara,  StyleSheetStub::BtDisable);
        StyleSheetStub::CfgBtStyle(ui->btWritePara, StyleSheetStub::BtDisable);
    }
    UpdateSlvData();
}

void MainWindow::Log(QString info)
{
    ui->statusBar->showMessage(info);
}

void MainWindow::on_btOpenDev_clicked()
{
    m_devLinker->show();
}

void MainWindow::on_btReadPara_clicked()
{
    emit SigGetDevDump();
}

void MainWindow::on_btWritePara_clicked()
{

}

void MainWindow::UpdateSlvData()
{
    // 曲线刷新
    auto data = m_dev->GetVoltageRawCurve();
    m_curve->clear();
    size_t idx = 0;
    for (auto o : data) {
        m_curve->append(idx++, o);
    }

    // 设备参数刷新
    if (m_dev->IsParaUpdated()) {
        UpdateSlvDataPara(ADC_CHANNEL_VOLT);
        UpdateSlvDataPara(ADC_CHANNEL_CURR);
        ui->txCalcRaw->setEnabled(true);
        ui->txCalcVal->setEnabled(true);
        ui->txRealVal->setEnabled(true);
    }

    // 文本刷新
    static char str[256] {0};
    sprintf(str, "Volt [%6.2f | %6d](%3llu pts)",
            m_dev->GetVoltageVal(), m_dev->GetVoltageRaw(), data.size());
    ui->lbSlvDataVolt->setText(QString::fromLatin1(str));
    sprintf(str, "Curr [%6.2f | %6d](%3llu pts)",
            m_dev->GetCurrentVal(), m_dev->GetCurrentRaw(), data.size());
    ui->lbSlvDataCurr->setText(QString::fromLatin1(str));
    sprintf(str, "%6d", m_dev->GetVoltageRaw());
    ui->lbCurrVal->setText(QString::fromLatin1(str));
}

void MainWindow::UpdateSlvDataPara(size_t curveIdx)
{
    auto dump = m_dev->GetDevDump();
    auto pCurve = m_ptsCurve[curveIdx];
    auto pChart = m_ptsChart[curveIdx];
    pCurve->clear();
    float xUnit = powf(10.0f, DEFAULT_X_UNIT);
    float yUnit = powf(10.0f, DEFAULT_Y_UNIT);
    double xVal, yVal;
    double xMin = 0.0, xMax = 0.0, yMin = 0.0, yMax = 0.0;
    for (size_t idx = 0; idx < ADC_CALIBPTS_MAX; idx++) {
        auto pts = dump.caliber[curveIdx].pts + idx;
        xVal = pts->x * xUnit;
        yVal = pts->y * yUnit;
        pCurve->append(xVal, yVal);
        xMin = std::min(xMin, xVal);
        xMax = std::max(xMax, xVal);
        yMin = std::min(yMin, yVal);
        yMax = std::max(yMax, yVal);
    }
    xMin -= (xMax - xMin) * 0.05;
    yMin -= (yMax - yMin) * 0.05;
    xMax += (xMax - xMin) * 0.05;
    yMax += (yMax - yMin) * 0.05;
    StyleSheetStub::CfgChartRange(pChart, xMin, xMax, yMin, yMax);
}

bool MainWindow::eventFilter(QObject *watched, QEvent *event)
{
    if (IsParaInput(watched) && event->type() == QEvent::KeyPress) {
        QKeyEvent *e = static_cast<QKeyEvent*>(event);
        if (e->key() == Qt::Key_Enter || e->key() == Qt::Key_Return) {
            ConfigSlvCalibPara(watched);
        }
    }
    return QWidget::eventFilter(watched, event);
}

bool MainWindow::IsParaInput(QObject *watched) const
{
    return (watched == ui->txCalcRaw || watched  == ui->txCalcVal || watched == ui->txRealVal);
}

void MainWindow::ConfigSlvCalibPara(QObject *watched)
{
    if (watched == nullptr) {
        return;
    }
    QLineEdit* sender = dynamic_cast<QLineEdit*>(watched);
    QString valStr = sender->text();
    double val = valStr.toFloat();
    sender->setText(QString::number(val, 'f', 2));
    if (sender == ui->txRealVal) {
        emit SigSetCurrData(ADC_CHANNEL_VOLT, val);
    } else {
        // 设置起止点
    }
}
